package ui;

import gragh.Equalivation;
import gragh.JoinGragh;
import gragh.ListRedundancy;
import gragh.Redundancy;
import gragh.Way;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.border.LineBorder;

import connector.Connection;
import constraint.*;
import constraint.join.Join;
import database.Schema;
import database.attset.SetAttribute;
import database.constraint.Constraint;
import database.constraint.ListBusinessConstraint;
import database.constraint.PrimaryKeyConstraint;
import database.constraint.ReferenceConstraint;
import database.fd.FDRedundancy;
import database.fd.FunctionalDependency;
import database.fd.ListFunctionDependency;
import database.relation.Relation;
import database.relation.Table;

import parser.ConstraintParser;
import ui.MyListAtt.MyLabel;
import utility.Utility;

import javax.swing.SwingConstants;
import java.awt.Font;

public class Window {

    private JFrame frame;
    JMenuBar menuBar;
    JMenu mnDatabase;
    JMenuItem mntmConnectDatabase;
    JMenuItem mntmExit;
    JPanel innerPanel;
    JPanel panelGlobalConstraint;
    JPanel panelGlobalFd;
//    JPanel panelGlobalSyn;
    JScrollPane scrollPane;
    JTabbedPane tabPanelContainer;
   
    
    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Window window = new Window();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Window() {
        initialize();
    }

    boolean isGlobalConstraintOpen = false;
    boolean isGlobalFdOpen = false;
    boolean isGlobalSynOpen = false;
    
    /**
     * Initialize the contents of the frame.
     */
    @SuppressWarnings("serial")
    private void initialize() {
        listTable = new ArrayList<Table>();
//      listRelation = new ArrayList<Relation>();
        listBConstraint = new ListBusinessConstraint();
        listFunctionDependency = new ListFunctionDependency();
        
        frame = new JFrame("Đánh giá CSDL và phát hiện dư thừa");
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setBounds(0, 0, 1280, 760);
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        
//      frame.getContentPane().setLayout(null);
        JPanel pnOuter = new JPanel();
        pnOuter.setLayout(null);
        pnOuter.setPreferredSize(new Dimension(1200, 700));

        
        
        JScrollPane scrlOuter = new JScrollPane(pnOuter);
        
        
//        btnShowTextAreaSynonym = new JButton("...");
//        btnShowTextAreaSynonym.addActionListener(new ActionListener() {
//            public void actionPerformed(ActionEvent e) {
//                if(!isGlobalSynOpen) {
//                    scrollPane.setBounds(0, 0, 1000, 460);
//                    panelGlobalConstraint.setVisible(false);
//                    panelGlobalFd.setVisible(false);
//                    panelGlobalSyn.setVisible(true);
//                    isGlobalConstraintOpen = false;
//                    isGlobalFdOpen = false;
//                    isGlobalSynOpen = true;
//                } else {
//                    scrollPane.setBounds(0, 0, 1000, 666);
//                    panelGlobalSyn.setVisible(false);
//                    isGlobalSynOpen = false;
//                }
//            }
//        });
//        btnShowTextAreaSynonym.setBounds(132, 5, 45, 30);
//        panelBottom.add(btnShowTextAreaSynonym);
        ////////////////////////////////////
        
        panelGlobalConstraint = new JPanel();
        panelGlobalConstraint.setBounds(0, 471, 1000, 200);
        //        pnOuter.add(panelGlobalConstraint);
                panelGlobalConstraint.setLayout(null);
                //        panelGlobalConstraint.setVisible(false);
                        
                        
                        panelGlobalFd = new JPanel();
                        panelGlobalFd.setBounds(0, 471, 1000, 200);
                        //        pnOuter.add(panelGlobalFd);
                                panelGlobalFd.setLayout(null);
                                //        panelGlobalFd.setVisible(false);
                                        
                                        tabPanelContainer = new JTabbedPane();
                                        tabPanelContainer.setBounds(0, 471, 1000, 207);
                                        pnOuter.add(tabPanelContainer);
                                        tabPanelContainer.setVisible(false);
                                        
                                        tabPanelContainer.addTab("Ràng buộc toàn vẹn", panelGlobalConstraint);
                                        
                                        tabPanelContainer.addTab("Phụ thuộc hàm", panelGlobalFd);
                                        
//        textAreaGlobalSyn = new JTextArea();
//        textAreaGlobalSyn.setRows(9);
//        scrollPaneGlobalSyn.setViewportView(textAreaGlobalSyn);
                                        //////////////////////////////////////////

                                        lblConstraintSavedMess = new JLabel ("");
                                        lblConstraintSavedMess.setHorizontalAlignment(SwingConstants.RIGHT);
                                        lblConstraintSavedMess.setBounds(710, 151, 200, 28);
                                        panelGlobalConstraint.add(lblConstraintSavedMess);
                                        
                                        
                                        
                                        
                                        
                                        
                                        
                                        /////////////////////////////////
                                        JScrollPane scrollPaneGlobalConstraint = new JScrollPane();
                                        scrollPaneGlobalConstraint.setBounds(0, 0, 910, 147);
                                        panelGlobalConstraint.add(scrollPaneGlobalConstraint);
                                        
                                        JScrollPane scrollPaneGlobalFd = new JScrollPane();
                                        scrollPaneGlobalFd.setBounds(0, 0, 910, 147);
                                        panelGlobalFd.add(scrollPaneGlobalFd);
                                        
                                        /////////////////////////////////////
                                        textAreaGlobalConstraint = new JTextArea();
                                        textAreaGlobalConstraint.setRows(9);
                                        textAreaGlobalConstraint.addKeyListener(new KeyAdapter() {
                                            @Override
                                            public void keyPressed(KeyEvent KE) {
                                                lblConstraintSavedMess.setText("");
                                            }
                                        });
                                        scrollPaneGlobalConstraint.setViewportView(textAreaGlobalConstraint);
                                        
                                        textAreaGlobalFd = new JTextArea();
                                        textAreaGlobalFd.setRows(9);
                                        textAreaGlobalFd.addKeyListener(new KeyAdapter() {
                                            @Override
                                            public void keyPressed(KeyEvent KE) {
                                                lblFdSavedMess.setText("");
                                            }
                                        });
                                        scrollPaneGlobalFd.setViewportView(textAreaGlobalFd);
                                        
                                        JButton btnClearConstraint = new JButton("Xóa");
                                        btnClearConstraint.addActionListener(new ActionListener() {
                                            public void actionPerformed(ActionEvent AE) {
                                                lblConstraintSavedMess.setText("");
                                                textAreaGlobalConstraint.setText("");
                                            }
                                        });
                                        btnClearConstraint.setBounds(919, 11, 76, 42);
                                        panelGlobalConstraint.add(btnClearConstraint);
                                        
                                        JButton btnReloadConstraint = new JButton("Tải lại");
                                        btnReloadConstraint.addActionListener(new ActionListener() {
                                            public void actionPerformed(ActionEvent AE) {
                                                lblConstraintSavedMess.setText("");
                                                textAreaGlobalConstraint.setText(txtGlobalConstraint);
                                            }
                                        });
                                        btnReloadConstraint.setBounds(919, 58, 76, 42);
                                        panelGlobalConstraint.add(btnReloadConstraint);
                                        
                                        btnSaveConstraint = new JButton("Lưu");
                                        btnSaveConstraint.addActionListener(new ActionListener() {
                                            public void actionPerformed(ActionEvent AE) {
                                                  // goi ham xu ly o ben duoi
                                                saveGlobalConstraint();
                                            }
                                        });
                                        btnSaveConstraint.setBounds(919, 105, 76, 42);
                                        panelGlobalConstraint.add(btnSaveConstraint);
                                        
                                        
                                        lblFdSavedMess = new JLabel ("");
                                        lblFdSavedMess.setHorizontalAlignment(SwingConstants.RIGHT);
                                        lblFdSavedMess.setBounds(710, 151, 200, 28);
                                        panelGlobalFd.add(lblFdSavedMess);
                                        
                                        JButton btnClearFd = new JButton("Xóa");
                                        btnClearFd.addActionListener(new ActionListener() {
                                            public void actionPerformed(ActionEvent AE) {
                                                lblFdSavedMess.setText("");
                                                textAreaGlobalFd.setText("");
                                            }
                                        });
                                        btnClearFd.setBounds(919, 11, 76, 42);
                                        panelGlobalFd.add(btnClearFd);
                                        
                                        JButton btnReloadFd = new JButton("Tải lại");
                                        btnReloadFd.addActionListener(new ActionListener() {
                                            public void actionPerformed(ActionEvent AE) {
                                                lblFdSavedMess.setText("");
                                                textAreaGlobalFd.setText(txtGlobalFd);
                                            }
                                        });
                                        btnReloadFd.setBounds(919, 58, 76, 42);
                                        panelGlobalFd.add(btnReloadFd);
                                        
                                        btnSaveFd = new JButton("Lưu");
                                        btnSaveFd.addActionListener(new ActionListener() {
                                            public void actionPerformed(ActionEvent AE) {
                                                  // goi ham xu ly o ben duoi
                                                saveListFd();
                                            }
                                        });
                                        btnSaveFd.setBounds(919, 105, 76, 42);
                                        panelGlobalFd.add(btnSaveFd);
//      scrlOuter.setBounds(0, 0, 1280, 717);
        
        innerPanel = new JPanel() {
            

            @Override
            public void paint(Graphics g) {
                super.paint(g);
                
                for(int i = 0; i < listTable.size(); i++) {
                    Table tb = listTable.get(i);
                    
//                  String ownerTable = tb.getTableName();
                    
                    ArrayList<Constraint> listConstraint = tb.getListConstraint();
                    
                    for(int j = 0; j < listConstraint.size(); j++) {
                        if(listConstraint.get(j).type == 1) {
                            ReferenceConstraint refConstraint = (ReferenceConstraint) listConstraint.get(j);
                                
                            TableInnerFrame ownerTIF = (TableInnerFrame) innerPanel.getComponent(refConstraint.ownerTableIndex);
                            TableInnerFrame refTIF = (TableInnerFrame) innerPanel.getComponent(refConstraint.refTableIndex);
                            // ket thuc lay TableInnerFrame
                            
                            drawLine(ownerTIF, refTIF, refConstraint, g);
                        }
                    }
                }
                
                
            }
            
        };
        
        innerPanel.setPreferredSize(new Dimension(1280, 800));
        
        scrollPane = new JScrollPane(innerPanel);
        innerPanel.setLayout(null);
        pnOuter.add(scrollPane);
        scrollPane.setBounds(0, 0, 1000, 666);
        
        pnRight = new JPanel();
        pnRight.setBackground(SystemColor.inactiveCaption);
        pnRight.setBounds(1010, 11, 258, 655);
        pnOuter.add(pnRight);
        pnRight.setLayout(null);
        
        panelBottom = new JPanel();
        panelBottom.setBorder(new LineBorder(new Color(0, 0, 0)));
        panelBottom.setBounds(0, 678, 1278, 37);
        pnOuter.add(panelBottom);
        panelBottom.setLayout(null);
        
        btnShowTextAreaConstraint = new JButton(">");
        btnShowTextAreaConstraint.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if(!isGlobalConstraintOpen) {
                    //dong -> mo
                    scrollPane.setBounds(0, 0, 1000, 460);
                    btnShowTextAreaConstraint.setText("<");
//                    panelGlobalConstraint.setVisible(true);
//                    panelGlobalFd.setVisible(false);
                    tabPanelContainer.setVisible(true);
                    isGlobalConstraintOpen = true;
                    isGlobalFdOpen = false;
                    isGlobalSynOpen = false;
                } else {
                    //mo -> dong
                    btnShowTextAreaConstraint.setText(">");
                    scrollPane.setBounds(0, 0, 1000, 666);
//                    panelGlobalConstraint.setVisible(false);
                    tabPanelContainer.setVisible(false);
                    isGlobalConstraintOpen = false;
                }
            }
        });
        btnShowTextAreaConstraint.setBounds(10, 5, 45, 30);
        panelBottom.add(btnShowTextAreaConstraint);
        
//        btnSaveSyn = new JButton("Save");
//        btnSaveSyn.setBounds(930, 150, 66, 42);
//        panelGlobalSyn.add(btnSaveSyn);
        ///////////////////////////////////
        frame.getContentPane().add(scrlOuter);
        
        menuBar = new JMenuBar();
        frame.setJMenuBar(menuBar);
        
        mnDatabase = new JMenu("Cơ sở dữ liệu");
        menuBar.add(mnDatabase);
        
        mntmConnectDatabase = new JMenuItem("Kết nối CSDL");
        mntmConnectDatabase.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                ConnectDatabase connectDB = new ConnectDatabase(frame);
                connectDB.setVisible(true);
                host = connectDB.getHost();
                serviceName = connectDB.getServiceName();
                username = connectDB.getUsername();
                password = connectDB.getPassword();
                port = connectDB.getPort();
                java.sql.Connection con = null;
                try {
                    con = Connection.getConnection(host, port, serviceName, username, password);
                    // ktra ket noi
                    listTable = Connection.getListRelation(con);
                    
                    // renew va tao listTable
                    renew();
                    listTable = Connection.getListRelation(con);
                    
                    int indexAuto = 0;
                    
                    //add index for relation
                    for(int i = 0; i < listTable.size(); i++) {
                        tb = listTable.get(i);
                        tb.index = i;
                      
                        Relation r = new Relation();
                      
                        r.setRname(tb.getTableName());
                      
                        for(int j = 0; j < tb.getListColumn().length; j++) {
                            r.add(j, indexAuto++);
                        }
                      
//                      listRelation.add(r);
                        Schema.listRelation.add(r);
                      
                        TableInnerFrame tmpTIF = new TableInnerFrame(tb);
                      
                        tmpTIF.getComponent(1).addMouseListener(new MouseAdapter() {

                            @Override
                            public void mouseClicked(MouseEvent e) {
                                TableInnerFrame tbFrame = (TableInnerFrame) ((Component)e.getSource()).getParent();
                                pnRight.setVisible(false);
                                pnRight.removeAll();
                                pnRight.add(new TableInfoPanel(tbFrame.tTable, listTable, Schema.listRelation));
                                pnRight.setVisible(true);
                            }
                          
                        });
                        tmpTIF.addComponentListener(new ComponentAdapter() {

                            @Override
                            public void componentMoved(ComponentEvent e) {
                                super.componentMoved(e);
                                innerPanel.repaint();
                            }
                        });
                     
                        innerPanel.add(tmpTIF);
                    }
                    // them index cho ref. constraint
                    updateIndexForRefCons();
                    
                    innerPanel.repaint();
                    innerPanel.setVisible(true);
                } catch (ClassNotFoundException e) {
                    System.out.println(e);
                } catch (SQLException e) {
                    System.out.println(e);
                } catch (java.lang.NullPointerException e) {
                    System.out.println(e);
                }

                connectDB.dispose();
            }
        });
        mnDatabase.add(mntmConnectDatabase);
        
        JMenuItem mntmLoadFile = new JMenuItem("Tải file");
        mntmLoadFile.setToolTipText("tải file đã lưu trên ổ đĩa thay vì phải kết nối đến CSDL");
        mntmLoadFile.addActionListener(new ActionListener() {
            @SuppressWarnings("unchecked")
            public void actionPerformed(ActionEvent arg0) {
                // renew toan bo
                renew();
              
                JFileChooser fChooser = new JFileChooser();
                int result = fChooser.showOpenDialog(frame);
                if(result == JFileChooser.APPROVE_OPTION) {
                    File f = fChooser.getSelectedFile();
                    try {
                        ObjectInputStream in = new ObjectInputStream(new FileInputStream(f));
                        
                        listTable = (ArrayList<Table>) in.readObject();
                        
                        txtGlobalConstraint = (String) in.readObject();
                        
                        textAreaGlobalConstraint.setText(txtGlobalConstraint);
                        
                        txtGlobalFd = (String) in.readObject();
                        
                        textAreaGlobalFd.setText(txtGlobalFd);
                        
                        listBConstraint = (ListBusinessConstraint) in.readObject();
                        
                        listFunctionDependency = (ListFunctionDependency) in.readObject();
                        
                        Schema.alreadyAnalysis = (Boolean) in.readObject();
                        
                        if (Schema.alreadyAnalysis) {
                            lsRedundancy = (ListRedundancy) in.readObject();
                            lsFunctionDependency = (ListFunctionDependency) in.readObject();
                            lsFDRedundancy = (ArrayList<FDRedundancy>) in.readObject();
                            lsBusinessConstraint = (ListBusinessConstraint) in.readObject();
                            lsPhysicalConstraint = (ArrayList<Constraint>) in.readObject();
                            lsWay = (ArrayList<Way>) in.readObject();
                        }
                        
//                        listRelation = new ArrayList<Relation>();
                        Schema.listRelation.clear();
                    } catch (FileNotFoundException e) {
                        System.out.println(e);
                    } catch (IOException e) {
                        System.out.println(e);
                    } catch (ClassNotFoundException e) {
                        System.out.println(e);
                    }
                    
                    int indexAuto = 0;
                    //add index for relation
                    for(int i = 0; i < listTable.size(); i++) {
                        tb = listTable.get(i);
                        
                        Relation r = new Relation();
                        
                        r.setRname(tb.getTableName());
                        
                        for(int j = 0; j < tb.getListColumn().length; j++) {
                            r.add(j, indexAuto++);
                        }
                        
                        Schema.listRelation.add(r);
                        
                        TableInnerFrame tmpTIF = new TableInnerFrame(tb);
                        
                        tmpTIF.getComponent(1).addMouseListener(new MouseAdapter() {

                            @Override
                            public void mouseClicked(MouseEvent e) {
                                TableInnerFrame tbFrame = (TableInnerFrame) ((Component)e.getSource()).getParent();
                                pnRight.setVisible(false);
                                pnRight.removeAll();
                                pnRight.add(new TableInfoPanel(tbFrame.tTable, listTable, Schema.listRelation));
                                pnRight.setVisible(true);
                            }
                            
                        });
                        
                        tmpTIF.addComponentListener(new ComponentAdapter() {

                            @Override
                            public void componentMoved(ComponentEvent e) {
                                super.componentMoved(e);
                                innerPanel.repaint();
                            }
                        });
                        
                        
                        innerPanel.add(tmpTIF);
                    }
//                    // them index cho ref. constraint
//                    updateIndexForRefCons();
                    innerPanel.repaint();
                    
                    innerPanel.setVisible(true);
                    
                }
            }
        });
        mnDatabase.add(mntmLoadFile);
        
        JMenuItem mntmSave = new JMenuItem("Lưu file");
        mntmSave.setToolTipText("lưu cơ sở dữ liệu lên ổ cứng để lần sau không cần phải kết nối đến CSDL nữa");
        mntmSave.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                JFileChooser fChooser = new JFileChooser();
                int result = fChooser.showSaveDialog(frame);
                if(result == JFileChooser.APPROVE_OPTION) {
                    File f = fChooser.getSelectedFile();
                    try {
                        f.createNewFile();
                        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
                        out.writeObject(listTable);
                        out.writeObject(txtGlobalConstraint);
                        out.writeObject(txtGlobalFd);
                        out.writeObject(listBConstraint);
                        out.writeObject(listFunctionDependency);
                        out.writeObject(Schema.alreadyAnalysis);
                        
                        // neu nhu da phan tich thi luu them ket qua phan tich
                        if (Schema.alreadyAnalysis) {
                            out.writeObject(lsRedundancy);
                            out.writeObject(lsFunctionDependency);
                            out.writeObject(lsFDRedundancy);
                            out.writeObject(lsBusinessConstraint);
                            out.writeObject(lsPhysicalConstraint);
                            out.writeObject(lsWay);
                        }
                        
                        out.flush();
                        out.close();
                    } catch (IOException e) {
                        System.out.println(e);
                    }
                }
            }
        });
        mnDatabase.add(mntmSave);
        
        JSeparator separator_2 = new JSeparator();
        mnDatabase.add(separator_2);
        
        mntmExit = new JMenuItem("Thoát");
        mnDatabase.add(mntmExit);
        
        JMenu mnProgrames = new JMenu("Chương trình chính");
        menuBar.add(mnProgrames);
        
        JMenuItem mntmAnalysis = new JMenuItem("Bắt đầu phân tích");
        mntmAnalysis.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                // TODO
                  // begin test
                if (!Schema.alreadyAnalysis) {
                    analysis();
                    Schema.alreadyAnalysis = true;
                }
                System.out.println(lsRedundancy.size());
                  // end test
                OutputFrame output = new OutputFrame(frame, lsRedundancy, lsWay, lsFDRedundancy, listTable, Schema.listRelation);
                output.setVisible(true);
            }
        });
        mnProgrames.add(mntmAnalysis);
    }
    
    public void renew() {
        Schema.alreadyAnalysis = false;
        
        // cac bien dung trong phan tich
        lsRedundancy = new ListRedundancy();
        lsFunctionDependency = new ListFunctionDependency();
        lsFDRedundancy = new ArrayList<FDRedundancy>();
        lsBusinessConstraint = new ListBusinessConstraint();
        lsPhysicalConstraint = new ArrayList<Constraint>();
        lsWay = new ArrayList<Way>();
        
        // cac bien listTable, listRelation, listFunctionDedendency
        listTable = new ArrayList<Table>();
        Schema.listRelation = new ArrayList<Relation>();
        listBConstraint= new ListBusinessConstraint();
        listFunctionDependency = new ListFunctionDependency();
        
        // don sach cac doi tuong giao dien
        innerPanel.removeAll();
        pnRight.removeAll();
        txtGlobalConstraint = "";
        textAreaGlobalConstraint.setText(txtGlobalConstraint);
        txtGlobalFd = "";
        textAreaGlobalFd.setText(txtGlobalFd);
        lblConstraintSavedMess.setText("");
        lblFdSavedMess.setText("");
    }
    
    private ListRedundancy lsRedundancy;
    private ListFunctionDependency lsFunctionDependency;
    private ArrayList<FDRedundancy> lsFDRedundancy;
    private ListBusinessConstraint lsBusinessConstraint;
    private ArrayList<Constraint> lsPhysicalConstraint;
    private ArrayList<Way> lsWay;
    
    public void analysis() {
          // reset All
        lsRedundancy = null;
        lsFunctionDependency = null;
        lsFDRedundancy = null;
        lsBusinessConstraint = null;
        lsPhysicalConstraint = null;
        lsWay = null;
        for (Relation r : Schema.listRelation) {
            r.resetAll();
        }

          // B1: cap nhat lai tap phu thuoc ham
          // B1.1 : lay FDs tu Schema
        lsFunctionDependency = (ListFunctionDependency) listFunctionDependency.clone();
          // B1.2 : lay FDs tu ref constraint
        
          // B2: tao list business constraitn toan cuc
        lsBusinessConstraint = new ListBusinessConstraint();
          // B2.1 lay global constraint
        for (constraint.Constraint bc : listBConstraint) {
            addUsefulBConstraint(lsBusinessConstraint, bc);
        }
          // B2.2 lay enter constraint cua tung table
          // B2.2 key hop chay chung voi refent constraint (phia duoi, cach day 8 dong code)
        
          // thuc hien tiep buoc B1.2
        for (constraint.Constraint bc : lsBusinessConstraint) {
            if (bc.type == 2) {
                Constraint_v2 c2 = (Constraint_v2) bc;
                if (c2.isFuncLeft == false && c2.isFuncRight == false) {
                    if (c2.left.get(0).index >= 0 &&  c2.left.get(0).index >= 0) {
                        FunctionalDependency fd_1 = new FunctionalDependency();
                        FunctionalDependency fd_2 = new FunctionalDependency();

                        int att = c2.left.get(0).index;
                        fd_1.left.add(att);
                        fd_2.right.add(att);

                        att = c2.right.get(0).index;
                        fd_1.right.add(att);
                        fd_2.left.add(att);

                        lsFunctionDependency.add(fd_1);
                        lsFunctionDependency.add(fd_2);
                    }
                }
            }
        }
        
          // B3: tao list referent constraint toan cuc
        lsPhysicalConstraint = new ArrayList<Constraint>();
        for (Table t : listTable) {
            for (Constraint pc : t.getListConstraint()) {
                if (pc.type == 1) {
                    lsPhysicalConstraint.add(pc);
                } else if (pc.type == 2) {
                    PrimaryKeyConstraint pkConstraint = (PrimaryKeyConstraint) pc;
                    FunctionalDependency fd = new FunctionalDependency();
                    ArrayList<String> lsStrKey = pkConstraint.getKey();
                    SetAttribute key = new SetAttribute();
                    SetAttribute nonKey = new SetAttribute();
                    
                    for (String k : lsStrKey) {
                        int indexK = Utility.getIndexAttributeInTable(t.getTableName(), k, listTable, Schema.listRelation);
                        key.add(indexK);
                        fd.left.add(indexK);
                    }
                    
                    for (Integer att : Schema.listRelation.get(t.index)) {
                        nonKey.add(att);
                    }
                    nonKey = nonKey.difference(key);
                    
                    for (Integer att : nonKey) {
                        fd.right.add(att);
                    }
                    
                    lsFunctionDependency.add(fd);
                }
            }
              // B2.2 chay o day
            for (constraint.Constraint bc : t.getListBConstraint()) {
                addUsefulBConstraint(lsBusinessConstraint, bc);
            }
        }

        
          // bat dau tien hanh phan tich dua vao listRelation, ref constraint va bus constraint
          // 1. xu ly business constraint
        ArrayList<Equalivation> equalivationMap = Equalivation.creatEqualivationMap(lsBusinessConstraint);
        JoinGragh gragh = new JoinGragh(listTable, Schema.listRelation);
        lsWay = gragh.getTheWays();
        lsRedundancy  = Redundancy.RedundancyAnalysis(equalivationMap, listTable, lsWay);
        lsRedundancy = gragh.pathsAnalysis(lsRedundancy);
        
        int i = 0;
        while (i < lsRedundancy.size()) {
            if (!lsRedundancy.get(i).havePath) {
                lsRedundancy.remove(i);
            } else {
                i++;
            }
        }
        
          // 2. xu ly phu thuoc ham
          // thuc hien tiep buoc B1.2
//        for (Way w : lsWay) {
//            FunctionalDependency fd_1 = new FunctionalDependency();
//            FunctionalDependency fd_2 = new FunctionalDependency();
//            for (Integer att : w.atts1) {
//                fd_1.left.add(att);
//                fd_2.right.add(att);
//            }
//            for (Integer att : w.atts2) {
//                fd_1.right.add(att);
//                fd_2.left.add(att);
//            }
//            lsFunctionDependency.add(fd_1);
//            lsFunctionDependency.add(fd_2);
//        }
        Schema.listFunctionDependency = lsFunctionDependency;
        
        lsFDRedundancy = new ArrayList<FDRedundancy>();
        FDRedundancy fdR = null;
        for (Relation r : Schema.listRelation) {
            boolean canAdd = true;
            if (!r.is2NormalForm()) {
                fdR = new FDRedundancy(r.get2NFViolentFDs(), "1NF", r.getRname());
            } else {
                if (!r.is3NormalForm()) {
                    fdR = new FDRedundancy(r.get3NFViolentFDs(), "2NF", r.getRname());
                } else {
                    if (!r.isBCNormalForm()) {
                        fdR = new FDRedundancy(r.getBCNFViolentFDs(), "3NF", r.getRname());
                    } else {
                        canAdd = false;
                    }
                }
            }
            
            if (canAdd) {
                for (FunctionalDependency fd : fdR.lsFd) {
                    ListFunctionDependency tmp_lsFd = new ListFunctionDependency();
                    tmp_lsFd.add(fd);
                    FDRedundancy tmp_fdR = new FDRedundancy(tmp_lsFd, fdR.form, fdR.relation);
                    lsFDRedundancy.add(tmp_fdR);
                }
            }
        }
    }
    
    public void addUsefulBConstraint(ListBusinessConstraint lsBConstraint, constraint.Constraint bc) {
        boolean canAdd = true;
        switch (bc.type) {
          // business constraint loai 1 ko dc add luc parse
        case 2:
        case 4: // loai 4 y chang loai 2 chi khac la co join dang cuoi
            Constraint_v2 c2 = (Constraint_v2) bc;
            if (c2.right.size() == 1 && c2.right.get(0).index == -1) {
                canAdd = isSimpleConstant(c2.right.get(0).idName);
            }
            break;
        case 3:
            Constraint_v3 c3 = (Constraint_v3) bc;
            canAdd = isSimpleConstant(c3.rightElement.idName);
            break;
        case 5:
            Constraint_v5 c5 = (Constraint_v5) bc;
            if (c5.elements.size() == 1 && c5.elements.get(0).index == -1) {
                canAdd = isSimpleConstant(c5.elements.get(0).idName);
            }
            break;
        case 6:
              // luon luon co the add
            break;
        }
        
        if(canAdd) {
            lsBConstraint.add(bc);
        }
    }
    
    public boolean isSimpleConstant(String cons) {
        char c = cons.charAt(0);
        boolean isSimple = true;
        
        switch (c) {
        case '{':
        case '(':
        case '[':
            isSimple = false;
            break;
        }
        
        return isSimple;
    }
    
    Table tb;
    
    private void drawLine(TableInnerFrame owner, TableInnerFrame ref, ReferenceConstraint constraint, Graphics g) {
//      int xSource = owner.getX();
//      int ySource = owner.getY();
//      int xDes = ref.getX();
//      int yDes = ref.getY();
        
        Rectangle o = getRectangleOfMyList(owner, constraint, 1);
        
        Rectangle r = getRectangleOfMyList(ref, constraint, 2);
        
//        System.out.println(o + " ---> " + r);
        
        this.drawLine(o, r, g);
        
//        this.drawLine(owner.getBounds(), ref.getBounds(), g);
    }
    
    private Rectangle getRectangleOfMyList(TableInnerFrame owner, ReferenceConstraint constraint, int o_Or_r) {
//        System.out.println("-----------------------------------");
//        System.out.println(owner.getBounds());
        
        ArrayList<MyListAtt.MyLabel> listAttOwner = new ArrayList<MyListAtt.MyLabel>();
        
        for(int i = 0; i < owner.myList.getComponentCount(); i++) {
            ArrayList<String> listAtt = o_Or_r == 1 ? constraint.getOwnerAtt() : constraint.getRefAtt();
            
            MyListAtt.MyLabel myAtt = (MyLabel) owner.myList.getComponent(i);
            
            for(int j = 0; j <listAtt.size(); j++) {
                if(myAtt.name.equals(listAtt.get(j))) {
                    listAttOwner.add(myAtt);
//                    System.out.println(myAtt.getBounds());
                }
            }
            
        }
        
        
        int minY = 100000;
        
        int maxY = 0;
        
        for(int i = 0; i < listAttOwner.size(); i++) {
            Rectangle r = listAttOwner.get(i).getBounds();
            
            minY = minY < r.y ? minY : r.y;
            
            maxY = maxY > r.y ? maxY : r.y;
        }
//        Rectangle r = listAttOwner.get(0).getBounds();
//        minY = r.y;
//        maxY = r.y;
        
        int y = minY;
        
        int width = 190;
        int height = maxY - minY + 20;

        Rectangle result = new Rectangle(owner.getBounds().x, owner.getBounds().y + y + 28, width, height);
//        System.out.println("->");
//        System.out.println(result);
//        System.out.println("-----------------------------------");
        
        return result;
    }
    
    private void drawLine(Rectangle r1, Rectangle r2, Graphics g) {
//        System.out.println("----------------------------------");
//        System.out.println(r1);
//        System.out.println(r2);
//        System.out.println("----------------------------------");
        
        Point r1LeftTop = new Point(r1.x, r1.y);
        Point r1RightTop = new Point(r1.x + r1.width, r1.y);
        Point r1LeftBottom = new Point(r1.x, r1.y + r1.height);
        Point r1RightBottom = new Point(r1.x + r1.width, r1.y + r1.height);
        
        Point r2LeftTop = new Point(r2.x, r2.y);
        Point r2RightTop = new Point(r2.x + r2.width, r2.y);
        Point r2LeftBottom = new Point(r2.x, r2.y + r2.height);
        Point r2RightBottom = new Point(r2.x + r2.width, r2.y + r2.height);
        
        if(r1RightTop.x < r2LeftTop.x) {
            int x1 = r1RightTop.x;
            int y1 = (r1RightTop.y + r1RightBottom.y) / 2;
            
            int x4 = r2LeftTop.x;
            int y4 = (r2LeftTop.y + r2LeftBottom.y) / 2;

            int x3 = (r1RightTop.x + r2LeftTop.x) / 2;
            int y3 = y4;
            
            int x2 = x3;
            int y2 = y1;
            
            g.drawLine(x1, y1, x2, y2);
            g.drawLine(x2, y2, x3, y3);
            g.drawLine(x3, y3, x4, y4);
        } else if (r2RightTop.x < r1LeftTop.x) {
            int x1 = r1LeftTop.x;
            int y1 = (r1LeftTop.y + r1LeftBottom.y) / 2;
            
            int x4 = r2RightTop.x;
            int y4 = (r2RightTop.y + r2RightBottom.y) / 2;
            
            int x2 = (r1LeftTop.x + r2RightTop.x) / 2;
            int y2 = y1;
            
            int x3 = x2;
            int y3 = y4;
            
            g.drawLine(x1, y1, x2, y2);
            g.drawLine(x2, y2, x3, y3);
            g.drawLine(x3, y3, x4, y4);
        } else {
            final int a = -20;
            if (r1LeftTop.x < r2LeftTop.x) {
                int x1 = r1LeftTop.x;
                int y1 = (r1LeftTop.y + r1LeftBottom.y) / 2;
                
                int x2 = x1 + a;
                int y2 = y1;
                
                int x3 = x2;
                int y3 = (r2LeftTop.y + r2LeftBottom.y) / 2;
                
                int x4 = r2LeftTop.x;
                int y4 = y3;
                
                g.drawLine(x1, y1, x2, y2);
                g.drawLine(x2, y2, x3, y3);
                g.drawLine(x3, y3, x4, y4);
            } else {
                int x4 = r2LeftTop.x;
                int y4 = (r2LeftTop.y + r2LeftBottom.y) / 2;
                
                int x3 = x4 + a;
                int y3 = y4;
                
                int x2 = x3;
                int y2 = (r1LeftTop.y + r1LeftBottom.y) / 2;
                
                int x1 = r1LeftTop.x;
                int y1 = y2;
                
                g.drawLine(x1, y1, x2, y2);
                g.drawLine(x2, y2, x3, y3);
                g.drawLine(x3, y3, x4, y4);
            }
            
        }
    }
    
    public void updateIndexForRefCons() {
        for (Table table : listTable) {
            for (Constraint cons : table.getListConstraint()) {
                if (cons.type == 1) {
//                  String ownerTable = ((ReferenceConstraint)cons).getOwnerTable();
                    int i = 0;
                    
                    // tinh index cua onwerTable
//                  for (i = 0; i < listTable.size(); i++) {
//                      if (listTable.get(i).getTableName().equals(ownerTable)) {
//                          break;
//                      }
//                  }
                    i = table.index;
                    ((ReferenceConstraint)cons).ownerTableIndex = i;
                    
                    // tinh index cua ownerAtt
                    String[] listCol1 = listTable.get(i).getListColumn();
                    for (String att : ((ReferenceConstraint)cons).getOwnerAtt()) {
                        for (int j = 0; j < listCol1.length; j++) {
                            if (listCol1[j].equals(att)) {
                                ((ReferenceConstraint)cons).ownerAttIndex.add(j);
                                break;
                            }
                        }
                    }
                    
                    
                    // tinh index cua refTable
                    String refTable = ((ReferenceConstraint)cons).getRefTable();
                    for (i = 0; i < listTable.size(); i++) {
                        if (listTable.get(i).getTableName().equals(refTable)) {
                            break;
                        }
                    }
                    ((ReferenceConstraint)cons).refTableIndex = i;
                    
                    // tinh index cua refAtt
                    String[] listCol2 = listTable.get(i).getListColumn();
                    for (String att : ((ReferenceConstraint)cons).getRefAtt()) {
                        for (int j = 0; j < listCol2.length; j++) {
                            if (listCol2[j].equals(att)) {
                                ((ReferenceConstraint)cons).refAttIndex.add(j);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
    
    ArrayList<Table> listTable = null;
//  ArrayList<Relation> listRelation;
    
    String host;
    String serviceName;
    String username;
    String password;
    String port;
    
    
    private JPanel pnRight;
    private JPanel panelBottom;
    private JButton btnShowTextAreaConstraint;
//    JButton btnShowTextAreaSynonym;
    private JTextArea textAreaGlobalConstraint;
    private JTextArea textAreaGlobalFd;
//  private JTextArea textAreaGlobalSyn;
    private JButton btnSaveConstraint;
    private JButton btnSaveFd;
//    private JButton btnSaveSyn;
    
    String txtGlobalConstraint = "";
    JLabel lblConstraintSavedMess;
    ListBusinessConstraint listBConstraint;
    
    String txtGlobalFd = "";
    JLabel lblFdSavedMess;
    ListFunctionDependency listFunctionDependency;
    
    public void saveListFd() {
        String[] lsFD = textAreaGlobalFd.getText().split("\n");
        boolean isError = false;
        String errorMess = "";
        ListFunctionDependency lsFd = new ListFunctionDependency();
        
        int i = 0;
        while (!isError && i < lsFD.length) {
            try {
                String[] sfd = lsFD[i].split("->");
                String s = sfd[0].trim();
                String[] arrLeft = s.substring(1, s.length()-1).split(",");
                s = sfd[1].trim();
                String[] arrRight = s.substring(1, s.length()-1).split(",");
                
                FunctionalDependency fd = new FunctionalDependency();
                int index = -1;
                String att = "";
                String[] arrS;
                
                  // xu ly ve trai
                int j = 0;
                while (!isError && j < arrLeft.length) {
                    att = arrLeft[j].replaceAll(" ", "");
                    arrS = att.replace('.', ',').split(",");
                    index = Utility.getIndexAttributeInTable(arrS[0], arrS[1], listTable, Schema.listRelation);
                    if (index == -1) {
                        isError = true;
                        errorMess = "bảng hay cột không hợp lệ";
                    } else {
                        fd.left.add(index);
                    }
                    j++;
                }
                
                  // xu ly ve phai
                if (!isError) {
                    j = 0;
                    while (!isError && j < arrRight.length) {
                        att = arrRight[j].replaceAll(" ", "");
                        arrS = att.replace('.', ',').split(",");
                        index = Utility.getIndexAttributeInTable(arrS[0], arrS[1], listTable, Schema.listRelation);
                        if (index == -1) {
                            isError = true;
                            errorMess = "bảng hay cột không hợp lệ";
                        } else {
                            fd.right.add(index);
                        }
                        j++;
                    }
                }
                
                if (!isError) {
                    lsFd.add(fd);
                }
            } catch (java.lang.StringIndexOutOfBoundsException e){
                isError = true;
                errorMess = "Lỗi cú pháp";
            } catch (java.lang.ArrayIndexOutOfBoundsException e) {
                isError = true;
                errorMess = "Lỗi cú pháp";
            } catch (Exception e) {
                System.out.println(e);
                isError = true;
                errorMess = "Lỗi không xác định";
            }
            i++;
        }
        
        if (!isError) {
              // save string va listFD
            txtGlobalFd = textAreaGlobalFd.getText();
            listFunctionDependency = lsFd;
              // thong bao thanh cong
            lblFdSavedMess.setForeground(Color.BLACK);
            lblFdSavedMess.setText("Lưu thành công");
              // project da bi thay doi
            Schema.alreadyAnalysis = false;
        } else {
              // thong bao loi
            lblFdSavedMess.setForeground(Color.RED);
            lblFdSavedMess.setText(errorMess);
        }
    }
    
    public void saveGlobalConstraint() {
          // xu ly so bo
        String strCons = textAreaGlobalConstraint.getText().replace('\n', ' ');
        if (strCons.length() > 1) {
            String endC = strCons.substring(strCons.length()-1, strCons.length());
            if (!endC.equals(";")) {
                strCons += ";";
            }
        } else {
            if (strCons.equals(";")) {
                strCons = " ;";
            } else {
                strCons += " ;";
            }
        }
        
          // xu ly: parse tung constraint mot
        ConstraintParser cp = new ConstraintParser();
        ListBusinessConstraint lsConstraint = new ListBusinessConstraint();
        String[] lsStrCons = strCons.split(";");
        int n = lsStrCons.length;
        boolean isError = false;
        String errorMess = "";
        
        for (int i = 0; i < n; i++) {
            if (isError) {
                break;
            }
            
            String strConstraint = lsStrCons[i].trim();
            if (strConstraint.equals("")) {
                continue;
            }
            
            try {
                constraint.Constraint c = cp.parse(strConstraint);
                int type = -1;
                ArrayList<String> lsTable = null;
                
                if (c != null)  {
                    type = c.type;
                }
                
                switch (type) {
                    case 1:
                        isError = true;
                        errorMess = "Phải nhiều hơn một bảng";
                        break;
                    case 2:
                          // synomyn
                        Constraint_v2 c2 = (Constraint_v2) c;
                        
                        if (c2.op.equals("=")
                                && c2.left.size() == 1 && c2.right.size() == 1
                                && !c2.isFuncLeft && !c2.isFuncRight
                                && c2.left.get(0).func.equals("") && c2.right.get(0).func.equals("")) {
                                
                            String[] arrSleft = c2.left.get(0).idName.replace('.', ',').split(",");
                            String[] arrSright = c2.right.get(0).idName.replace('.', ',').split(",");
                            if (!arrSleft[0].equals(arrSright[0])) {
                                int index = Utility.getIndexAttributeInTable(arrSleft[0], arrSleft[1], listTable, Schema.listRelation);
                                if (index == -1) {
                                    isError = true;
                                    errorMess = "Bảng hay cột không hợp lệ";
                                } else {
                                    c2.left.get(0).index = index;
                                }
                                
                                if (!isError) {
                                    index = Utility.getIndexAttributeInTable(arrSright[0], arrSright[1], listTable, Schema.listRelation);
                                    if (index == -1) {
                                        isError = true;
                                        errorMess = "Bảng hay cột không hợp lệ";
                                    } else {
                                        c2.right.get(0).index = index;
                                    }
                                }
                            } else {
                                isError = true;
                                errorMess = "Phải nhiều hơn một bảng";
                            }
                        } else {
                            isError = true;
                            errorMess = "Lỗi cú pháp";
                        }
                        
                        if (!isError) {
                              // add constraint loai 2 vao list constraint
                            lsConstraint.add(c2);
                        }
                        break;
                    case 3:
                        Constraint_v3 c3 = (Constraint_v3) c;
                        Group g = c3.leftGroup;
                        
                          // kiem tra cai group
                        errorMess = checkGroup(g);
                        if (!errorMess.equals("")) {
                            isError = true;
                        }

                        if (!isError && c3.op.equals("=")) {
                              // add constraint loai 3 vao list constraint
                            lsConstraint.add(c3);
                        }
                        break;
                    case 4:
                        Constraint_v4 c4 = (Constraint_v4) c;
                        lsTable = new ArrayList<String>();
                        
                          // ktra cai join
                        errorMess = checkJoin(c4.join);
                        if (!errorMess.equals("")) {
                            isError = true;
                        } else {
                            for (Join jo : c4.join) {
                                if (!lsTable.contains(jo.table1)) {
                                    lsTable.add(jo.table1);
                                }
                                if (!lsTable.contains(jo.table2)) {
                                    lsTable.add(jo.table2);
                                }
                            }
                        }
                        
                          // ktra ve trai
                        if (!isError) {
                            errorMess = checkListElements(c4.left);
                            if (!errorMess.equals("")) {
                                isError = true;
                            } else {
                                int j = 0;
                                while (!isError && j < c4.left.size()) {
                                    String[] arrS = c4.left.get(j).idName.replace('.', ',').split(",");
                                    isError = !lsTable.contains(arrS[0]);
                                    j++;
                                }
                                if (isError) {
                                    errorMess = "Bảng không hợp lệ";
                                }
                            }
                        }
                        
                          // ktra ve phai
                        if (!isError) {    
                            errorMess = checkListElements(c4.right);
                            if (!errorMess.equals("")) {
                                isError = true;
                            } else {
                                  // kiem tra illegal table
                                int j = 0;
                                while (!isError && j < c4.right.size()) {
                                    String[] arrS = c4.right.get(j).idName.replace('.', ',').split(",");
                                    isError = !lsTable.contains(arrS[0]);
                                    j++;
                                }
                                if (isError) {
                                    errorMess = "Bảng không hợp lệ";
                                }
                            } 
                        }
                        
                        if (!isError && c4.op.equals("=")) {
                          // add constraint loai 4 vao list constraint
                            lsConstraint.add(c4);
                        }
                        break;
                    case 5:
                        Constraint_v5 c5 = (Constraint_v5) c;
                        lsTable = new ArrayList<String>();
                        
                          // ktra cai join
                        errorMess = checkJoin(c5.join);
                        if (!errorMess.equals("")) {
                            isError = true;
                        } else {
                            for (Join jo : c5.join) {
                                if (!lsTable.contains(jo.table1)) {
                                    lsTable.add(jo.table1);
                                }
                                if (!lsTable.contains(jo.table2)) {
                                    lsTable.add(jo.table2);
                                }
                            }
                        }
                        
                          // kiem tra cai element
                        if (!isError) {
                            errorMess = checkListElements(c5.elements);
                            if (!errorMess.equals("")) {
                                isError = true;
                            } else {
                                  // kiem tra illegal table
                                int j = 0;
                                while (!isError && j < c5.elements.size()) {
                                    String[] arrS = c5.elements.get(j).idName.replace('.', ',').split(",");
                                    isError = !lsTable.contains(arrS[0]);
                                    j++;
                                }
                                if (isError) {
                                    errorMess = "Bảng không hợp lệ";
                                }
                            }
                        }
                        
                          // kiem tra cai group
                          // cai group da kiem tra illegal table roi
                        if (!isError) {
                            errorMess = checkGroup(c5.group);
                            if (!errorMess.equals("")) {
                                isError = true;
                            }
                        }
                        
                        if (!isError && c5.op.equals("=")) {
                          // add constraint loai 5 vao list constraint
                            lsConstraint.add(c5);
                        }
                        break;
                    case 6:
                        Constraint_v6 c6 = (Constraint_v6) c ;
                        
                          // kiem tra cai join
                        errorMess = checkJoin(c6.join);
                        if (!errorMess.equals("")) {
                            isError = true;
                        }
                        
                          // kiem tra group o ve trai
                        if (!isError) {
                            errorMess = checkGroup(c6.leftGroup);
                            if (!errorMess.equals("")) {
                                isError = true;
                            }
                        }
                        
                          // kiem tra group o ve phai
                        if (!isError) {
                            errorMess = checkGroup(c6.rightGroup);
                            if (!errorMess.equals("")) {
                                isError = true;
                            }
                        }
                            
                        if (!isError && c6.op.equals("=")) {
                            // add constraint loai 6 vao list constraint
                              lsConstraint.add(c6);
                        }
                        break;
                    default:
                        isError = true;
                        errorMess = "Lỗi cú pháp";
                        break;
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                  // loi cu phap khi parse
                isError = true;
                errorMess = "Lỗi không xác định";
            }
        }
        
        
        if (!isError) {
            listBConstraint = lsConstraint;
            txtGlobalConstraint = textAreaGlobalConstraint.getText();
              // in ra thong bao thanh cong
            lblConstraintSavedMess.setForeground(Color.BLACK);
            lblConstraintSavedMess.setText("Lưu thành công");
              // project da bi thay doi
            Schema.alreadyAnalysis = false;
        } else {
              // in ra thong bao loi
            lblConstraintSavedMess.setForeground(Color.RED);
            lblConstraintSavedMess.setText(errorMess);
        }
    }
    
    public String checkListElements(ArrayList<Element> lsE) {
        boolean isError = false;
        String errorMess = "";
        Table table = null;
        String[] lsAtts;
        String[] tmp_ArrStr;
        
        String sTb;
        String sAtt;
        int k = 0;
        boolean found = false;
        
        int j = 0;
        while (!isError && j < lsE.size()) {
            tmp_ArrStr = lsE.get(j).idName.replace('.', ',').split(",");
            sTb = tmp_ArrStr[0];
            sAtt = tmp_ArrStr[1];
            
              // tim index cua bang sTb
            k = 0;
            found = false;
            while (!found && k < listTable.size()) {
                if (sTb.equals(listTable.get(k).getTableName())) {
                    found = true;
                    table = listTable.get(k);
                }
                k++;
            }
            if (!found) {
                isError = true;
                errorMess = "Bảng không hợp lệ";
            }
            
            if(!isError) {
                  // tim lsAtt khi biet gia tri index cua table
                lsAtts = table.getListColumn();
                
                  // tim va gan index cho thuoc tinh
                k = 0;
                found = false;
                while (!found && k < lsAtts.length) {
                    if (sAtt.equals(lsAtts[k])) {
                        found = true;
                        lsE.get(j).index = Schema.listRelation.get(table.index).get(k);
                        lsE.get(j).tableIndex = table.index;
                    }
                    k++;
                }
                if (!found) {
                    isError = true;
                    errorMess = "Cột không hợp lệ";
                }
            }
            j++;
        }
        
        return errorMess;
    }
    
    public String checkJoin(ArrayList<Join> lsJoins) {
        boolean isError = false;
        String errorMess = "";
        Table table = null;
        String[] lsAtts;
        
        String[] tmp1_ArrStr;
        String[] tmp2_ArrStr;
        String sAtt1 = "";
        String sAtt2 = "";
        
        int k  = 0;
        boolean found = false;
        
        int i_gj = 0;
        while (!isError && i_gj < lsJoins.size()) {
            Join join = lsJoins.get(i_gj);
            
              // chuan hoa ve phai va ve trai cua dien kien
            tmp1_ArrStr = join.left.replace('.', ',').split(",");
            tmp2_ArrStr = join.right.replace('.', ',').split(",");
            if (join.table1.equals(join.table2)) {
                isError = true;
                errorMess = "Điều kiện JOIN không hợp lệ";
            }
            if (!isError) {
                if (tmp1_ArrStr[0].equals(join.table1) && tmp2_ArrStr[0].equals(join.table2)) {
                    sAtt1 = tmp1_ArrStr[1];
                    sAtt2 = tmp2_ArrStr[1];
                } else if (tmp1_ArrStr[0].equals(join.table2) && tmp2_ArrStr[0].equals(join.table1)) {
                    sAtt1 = tmp2_ArrStr[1];
                    sAtt2 = tmp1_ArrStr[1];
                } else {
                    isError = true;
                    errorMess = "Điều kiện JOIN không hợp lệ";
                }
            }

              // table1
            if (!isError) {
                  // tim index cho table1
                k = 0;
                found = false;
                while (!found && k < listTable.size()) {
                    if (join.table1.equals(listTable.get(k).getTableName())) {
                        found = true;
                        join.indexTable1 = k;
                        table = listTable.get(k);
                    }
                    k++;
                }
                if (!found) {
                    isError = true;
                    errorMess = "Bảng không hợp lệ trong điều kiện JOIN";
                }
                
                if (!isError) {
                      // tim lsAtt khi biet gia tri index cua table1
                    lsAtts = table.getListColumn();
                    
                      // tim va gan index cho thuoc tinh 
                    k = 0;
                    found = false;
                    while (!found && k < lsAtts.length) {
                        if (sAtt1.equals(lsAtts[k])) {
                            found = true;
                            join.indexAtt1 = Schema.listRelation.get(table.index).get(k);
                        }
                        k++;
                    }
                    if (!found) {
                        isError = true;
                        errorMess = "Cột không hợp lệ trong điều kiện JOIN";
                    }
                }
            }
            
              // table2
            if (!isError) {
                  // tim index cho table2
                k = 0;
                found = false;
                while (!found && k < listTable.size()) {
                    if (join.table2.equals(listTable.get(k).getTableName())) {
                        found = true;
                        join.indexTable2 = k;
                        table = listTable.get(k);
                    }
                    k++;
                }
                if (!found) {
                    isError = true;
                    errorMess = "Bảng không hợp lệ trong điều kiện JOIN";
                }
              
                if (!isError) {
                      // tim lsAtt khi biet gia tri index cua table1
                    lsAtts = table.getListColumn();
                  
                      // tim va gan index cho thuoc tinh 
                    k = 0;
                    found = false;
                    while (!found && k < lsAtts.length) {
                        if (sAtt2.equals(lsAtts[k])) {
                            found = true;
                            join.indexAtt2 = Schema.listRelation.get(table.index).get(k);
                        }
                        k++;
                    }
                    if (!found) {
                        isError = true;
                        errorMess = "Cột không hợp lệ trong điều kiện JOIN";
                    }
                }
            }
            i_gj++;
        }
        
        return errorMess;
    }
    
    public String checkGroup(Group g) {
        boolean isError = false;
        String errorMess = "";
        Table table = null;
        String[] lsAtts;
        
        boolean found = false;
        int k = 0;

        String[] tmp_ArrStr;
        ArrayList<String> lsTable = new ArrayList<String>();
        
          // kiem tra cai join va tim ra cac bang hop le
        if (!isError) {
            errorMess = checkJoin(g.join);
            if (!errorMess.equals("")) {
                isError = true;
            } else {
                if (g.join.size() < 1) {
                    String[] arrS = g.subGroups.get(0).elements.get(0).idName.replace('.', ',').split(",");
                    lsTable.add(arrS[0]);
                      // neu checkJoin ko co lo thi table arrS[0] chac chan se dc tim thay trong listTable
                    g.indexTables.add(Utility.getIndexOfTable(arrS[0], listTable));
                } else {
                    for (int i = 0; i < g.join.size(); i++) {
                        Join join = g.join.get(i);
                        if (!lsTable.contains(join.left)) {
                            lsTable.add(join.left);
                        }
                        if (!lsTable.contains(join.right)) {
                            lsTable.add(join.right);
                        }
                          // cap nhan indexTables
                        if (!g.indexTables.contains(join.indexTable1)) {
                            g.indexTables.add(join.indexTable1);
                        }
                        if (!g.indexTables.contains(join.indexTable2)) {
                            g.indexTables.add(join.indexTable2);
                        }
                    }
                }
            }
        }
        
        if (!isError) {
              // kiem tra sub group
            int i = 0;
            while (!isError && i < g.subGroups.size()) {
                SubGroup sg = g.subGroups.get(i);
                errorMess = checkListElements(sg.elements);
                if (!errorMess.equals("")) {
                    if (sg.elements.size() == 1) {
                        String[] arrS = sg.elements.get(0).idName.replace('.', ',').split(",");
                        if (lsTable.contains(arrS[0]) && arrS[1].equals("*")) {
                            errorMess = "";
                            sg.elements.get(0).index = -2;
                        } else {
                            isError = true;
                        }
                    } else {
                        isError = true;
                    }
                } else {
                      // kiem tra cac thuoc tinh co nam trong cac bang dc join hay khong
                    k = 0;
                    while (!isError && k < sg.elements.size()) {
                        String[] arrStr = sg.elements.get(k).idName.replace('.', ',').split(",");
                        String str = arrStr[0];
                        if (!lsTable.contains(str)) {
                            isError = true;
                            errorMess = "Bảng hay cột không hợp lệ";
                        }
                        k++;
                    }
                }
                i++;
            }
        }
        
        if (!isError) {
              // kiem tra thuoc tinh nhom
            int j = 0;
            while (!isError && j < g.groupAtt.size()) {
                tmp_ArrStr = g.groupAtt.get(j).replace('.', ',').split(",");
                String sTb = tmp_ArrStr[0];
                String sAtt = tmp_ArrStr[1];
                
                  // kiem tra table (truoc dau .)
                k = 0;
                found = false;
                while (!found && k < listTable.size()) {
                    found = sTb.equals(listTable.get(k).getTableName());
                    k++;
                }
                if (!found) {
                    isError = true;
                    errorMess = "Bảng không hợp lệ trong thuộc tính nhóm";
                } else {
                    k--;
                    if (lsTable.contains(sTb)) {
                        table = listTable.get(k);
                    } else {
                        isError = true;
                        errorMess = "Bảng không hợp lệ trong thuộc tính nhóm";
                    }
                }
                
                  // kiem tra thuoc tinh (sau dau .)
                if (!isError) {
                    lsAtts = table.getListColumn();
                    k = 0;
                    found = false;
                    while (!found && k < lsAtts.length) {
                        found = sAtt.equals(lsAtts[k]);
                        k++;
                    }
                    if (!found) {
                        isError = true;
                        errorMess = "Cột không hợp lệ trong thuộc tính nhóm";
                    }
                }
                j++;
            }
        }
        
        return errorMess;
    }
}
